/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
/*
 * This copy of Woodstox XML processor is licensed under the
 * Apache (Software) License, version 2.0 ("the License").
 * See the License for details about distribution rights, and the
 * specific rights regarding derivate works.
 *
 * You may obtain a copy of the License at:
 *
 * http://www.apache.org/licenses/
 *
 * A copy is also included in the downloadable source code package
 * containing Woodstox, in file "ASL2.0", under the same directory
 * as this file.
 */
package com.je.bpm.core.converter.converter;

import com.je.bpm.core.converter.converter.child.BaseChildElementParser;
import com.je.bpm.core.converter.converter.child.config.TaskListenerConfigParser;
import com.je.bpm.core.converter.converter.util.BpmnXMLUtil;
import com.je.bpm.core.model.BaseElement;
import com.je.bpm.core.model.BpmnModel;
import com.je.bpm.core.model.ExtensionAttribute;
import com.je.bpm.core.model.config.task.TaskBasicConfigImpl;
import com.je.bpm.core.model.config.task.TaskListenerConfigImpl;
import com.je.bpm.core.model.task.KaiteBaseUserTask;
import com.je.bpm.core.model.task.KaiteTask;
import org.apache.commons.lang3.StringUtils;

import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 基础任务配置转换器
 */
public abstract class KaiteTaskXmlConverter extends BaseBpmnXMLConverter {

    protected Map<String, BaseChildElementParser> childParserMap = new HashMap<String, BaseChildElementParser>();

    /**
     * default attributes taken from bpmn spec and from activiti extension
     */
    protected static final List<ExtensionAttribute> defaultTaskAttributes = new ArrayList<>();

    public KaiteTaskXmlConverter() {
        TaskListenerConfigParser taskListenerConfigParser = new TaskListenerConfigParser();
        childParserMap.put(taskListenerConfigParser.getElementName(), taskListenerConfigParser);

        defaultTaskAttributes.add(new ExtensionAttribute(ACTIVITI_EXTENSIONS_NAMESPACE, ATTRIBUTE_TASK_USER_CATEGORY));
        defaultTaskAttributes.add(new ExtensionAttribute(ACTIVITI_EXTENSIONS_NAMESPACE, ATTRIBUTE_TASK_SERVICE_EXTENSIONID));
        defaultTaskAttributes.add(new ExtensionAttribute(ACTIVITI_EXTENSIONS_NAMESPACE, ATTRIBUTE_TASK_USER_SKIP_EXPRESSION));
    }

    public void taskBaseParser(KaiteBaseUserTask kaiteUserTask, XMLStreamReader xtr) {
        TaskBasicConfigImpl taskBasicConfig = new TaskBasicConfigImpl();
        taskBasicConfig.setFormSchemeName(xtr.getAttributeValue(null, PROPERTY_TASK_PROPERTIES_FORMSCHEMENAME));
        taskBasicConfig.setFormSchemeId(xtr.getAttributeValue(null, PROPERTY_TASK_PROPERTIES_FORMSCHEMEID));
        taskBasicConfig.setListSynchronization(Boolean.valueOf(xtr.getAttributeValue(null, PROPERTY_TASK_PROPERTIES_LISTSYNCHRONIZATION)));
        taskBasicConfig.setRetrieve(Boolean.valueOf(xtr.getAttributeValue(null, PROPERTY_TASK_PROPERTIES_RETRIEVE)));
        taskBasicConfig.setUrge(Boolean.valueOf(xtr.getAttributeValue(null, PROPERTY_TASK_PROPERTIES_URGE)));
        taskBasicConfig.setInvalid(Boolean.valueOf(xtr.getAttributeValue(null, PROPERTY_TASK_PROPERTIES_INVALID)));
        taskBasicConfig.setDelegate(Boolean.valueOf(xtr.getAttributeValue(null, PROPERTY_TASK_PROPERTIES_DELEGATE)));
        taskBasicConfig.setTransfer(Boolean.valueOf(xtr.getAttributeValue(null, PROPERTY_TASK_PROPERTIES_TRANSFER)));
        taskBasicConfig.setFormEditable(Boolean.valueOf(xtr.getAttributeValue(null, PROPERTY_TASK_PROPERTIES_FORMEDITABLE)));
        taskBasicConfig.setRemind(Boolean.valueOf(xtr.getAttributeValue(null, PROPERTY_TASK_PROPERTIES_REMIND)));
        taskBasicConfig.setSimpleApproval(Boolean.valueOf(xtr.getAttributeValue(null, PROPERTY_TASK_PROPERTIES_SIMPLEAPPROVAL)));
        taskBasicConfig.setSelectAll(Boolean.valueOf(xtr.getAttributeValue(null, PROPERTY_TASK_PROPERTIES_SELECTALL)));
        taskBasicConfig.setAsynTree(Boolean.valueOf(xtr.getAttributeValue(null, PROPERTY_TASK_PROPERTIES_ASYNTREE)));
        taskBasicConfig.setJump(Boolean.valueOf(xtr.getAttributeValue(null, PROPERTY_TASK_PROPERTIES_JUMP)));
        taskBasicConfig.setLogicalJudgment(Boolean.valueOf(xtr.getAttributeValue(null, PROPERTY_TASK_PROPERTIES_LOGICALJUDGMENT)));
        taskBasicConfig.setSecurityEnable(Boolean.valueOf(xtr.getAttributeValue(null, SECURITY_ENABLE)));
        taskBasicConfig.setSecurityCode(xtr.getAttributeValue(null, SECURITY_CODE));
        taskBasicConfig.setCountersign(Boolean.valueOf(xtr.getAttributeValue(null, COUNTERSIGN)));
        taskBasicConfig.setSignBack(Boolean.valueOf(xtr.getAttributeValue(null, SIGN_BACK)));
        taskBasicConfig.setForcedSignatureBack(Boolean.valueOf(xtr.getAttributeValue(null, FORCED_SIGNATURE_BACK)));
        taskBasicConfig.setStaging(Boolean.valueOf(xtr.getAttributeValue(null, STAGING)));
        taskBasicConfig.setBasicRuntimeTuning(Boolean.valueOf(xtr.getAttributeValue(null, BASIC_RUNTIME_TUNING)));
        taskBasicConfig.setInitiatorCanCancel(Boolean.valueOf(xtr.getAttributeValue(null, ATTRIBUTE_PROCESS_INITIATOR_CANCANCEL)));
        taskBasicConfig.setInitiatorCanInvalid(Boolean.valueOf(xtr.getAttributeValue(null, ATTRIBUTE_PROCESS_INITIATOR_CANINVALID)));
        taskBasicConfig.setInitiatorCanUrged(Boolean.valueOf(xtr.getAttributeValue(null, ATTRIBUTE_PROCESS_INITIATOR_CANURGED)));
        kaiteUserTask.setTaskBasicConfig(taskBasicConfig);
    }

    @Override
    protected void writeAdditionalAttributes(BaseElement element, BpmnModel model, XMLStreamWriter xtw) throws Exception {
        KaiteTask kaiteTask = (KaiteTask) element;
        writeQualifiedAttribute(ATTRIBUTE_TASK_USER_CATEGORY, kaiteTask.getCategory(), xtw);
        if (StringUtils.isNotEmpty(kaiteTask.getExtensionId())) {
            writeQualifiedAttribute(ATTRIBUTE_TASK_SERVICE_EXTENSIONID, kaiteTask.getExtensionId(), xtw);
        }
        TaskBasicConfigImpl taskBasicConfig = kaiteTask.getTaskBasicConfig();
        xtw.writeAttribute(PROPERTY_TASK_PROPERTIES_FORMSCHEMENAME, taskBasicConfig.getFormSchemeName());
        xtw.writeAttribute(PROPERTY_TASK_PROPERTIES_FORMSCHEMEID, taskBasicConfig.getFormSchemeId());
        xtw.writeAttribute(PROPERTY_TASK_PROPERTIES_LISTSYNCHRONIZATION, String.valueOf(taskBasicConfig.getListSynchronization()));
        xtw.writeAttribute(PROPERTY_TASK_PROPERTIES_RETRIEVE, String.valueOf(taskBasicConfig.getRetrieve()));
        xtw.writeAttribute(PROPERTY_TASK_PROPERTIES_URGE, String.valueOf(taskBasicConfig.getUrge()));
        xtw.writeAttribute(PROPERTY_TASK_PROPERTIES_INVALID, String.valueOf(taskBasicConfig.getInvalid()));
        xtw.writeAttribute(PROPERTY_TASK_PROPERTIES_DELEGATE, String.valueOf(taskBasicConfig.getDelegate()));
        xtw.writeAttribute(PROPERTY_TASK_PROPERTIES_TRANSFER, String.valueOf(taskBasicConfig.getTransfer()));
        xtw.writeAttribute(PROPERTY_TASK_PROPERTIES_FORMEDITABLE, String.valueOf(taskBasicConfig.getFormEditable()));
        xtw.writeAttribute(PROPERTY_TASK_PROPERTIES_REMIND, String.valueOf(taskBasicConfig.getRemind()));
        xtw.writeAttribute(PROPERTY_TASK_PROPERTIES_SIMPLEAPPROVAL, String.valueOf(taskBasicConfig.getSimpleApproval()));
        xtw.writeAttribute(PROPERTY_TASK_PROPERTIES_SELECTALL, String.valueOf(taskBasicConfig.getSelectAll()));
        xtw.writeAttribute(PROPERTY_TASK_PROPERTIES_ASYNTREE, String.valueOf(taskBasicConfig.getAsynTree()));
        xtw.writeAttribute(PROPERTY_TASK_PROPERTIES_JUMP, String.valueOf(taskBasicConfig.getJump()));
        xtw.writeAttribute(PROPERTY_TASK_PROPERTIES_LOGICALJUDGMENT, String.valueOf(taskBasicConfig.getLogicalJudgment()));
        xtw.writeAttribute(SECURITY_ENABLE, String.valueOf(taskBasicConfig.getSecurityEnable()));
        xtw.writeAttribute(SECURITY_CODE, String.valueOf(taskBasicConfig.getSecurityCode()));
        xtw.writeAttribute(COUNTERSIGN, String.valueOf(taskBasicConfig.getCountersign()));
        xtw.writeAttribute(SIGN_BACK, String.valueOf(taskBasicConfig.getSignBack()));
        xtw.writeAttribute(FORCED_SIGNATURE_BACK, String.valueOf(taskBasicConfig.getForcedSignatureBack()));
        xtw.writeAttribute(STAGING, String.valueOf(taskBasicConfig.getStaging()));
        xtw.writeAttribute(BASIC_RUNTIME_TUNING, String.valueOf(taskBasicConfig.getBasicRuntimeTuning()));
        xtw.writeAttribute(ATTRIBUTE_PROCESS_INITIATOR_CANCANCEL, String.valueOf(taskBasicConfig.isInitiatorCanCancel()));
        xtw.writeAttribute(ATTRIBUTE_PROCESS_INITIATOR_CANINVALID, String.valueOf(taskBasicConfig.isInitiatorCanInvalid()));
        xtw.writeAttribute(ATTRIBUTE_PROCESS_INITIATOR_CANURGED, String.valueOf(taskBasicConfig.isInitiatorCanUrged()));
        // write custom attributes
        BpmnXMLUtil.writeCustomAttributes(kaiteTask.getAttributes().values(), xtw, defaultElementAttributes, defaultActivityAttributes, defaultTaskAttributes);
    }

    @Override
    protected void writeAdditionalChildElements(BaseElement element, BpmnModel model, XMLStreamWriter xtw) throws Exception {
        KaiteTask kaiteTask = (KaiteTask) element;
        writeListenerConfig(kaiteTask.getTaskListenerConfig(), xtw);
    }

    private void writeListenerConfig(TaskListenerConfigImpl taskListenerConfig, XMLStreamWriter xtw) throws Exception {
        xtw.writeStartElement(BPMN2_PREFIX, ELEMENT_USERTASK_LISTENER_CONFIG, BPMN2_NAMESPACE);
        for (TaskListenerConfigImpl.ListenerConfig each : taskListenerConfig.getListenerConfigs()) {
            writeEachListenerConfig(each, xtw);
        }
        xtw.writeEndElement();
    }

    private void writeEachListenerConfig(TaskListenerConfigImpl.ListenerConfig listenerConfig, XMLStreamWriter xtw) throws Exception {
        xtw.writeStartElement(BPMN2_PREFIX, ELEMENT_USERTASK_LISTENER, BPMN2_NAMESPACE);
        writeQualifiedAttribute(ATTRIBUTE_USERTASK_LISTENER_TYPE, listenerConfig.getType(), xtw);
        writeQualifiedAttribute(ATTRIBUTE_USERTASK_LISTENER_STRATEGY, listenerConfig.getStategy(), xtw);
        writeQualifiedAttribute(ATTRIBUTE_USERTASK_LISTENER_BEANNAME, listenerConfig.getBeanName(), xtw);
        writeQualifiedAttribute(ATTRIBUTE_USERTASK_LISTENER_FIELDVALUES, listenerConfig.getFieldSetValueStr(), xtw);
        xtw.writeEndElement();
    }

}
